package com.iqiyi.pps.epg.core.service.record;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iqiyi.kiwi.utils.Configuration;
import com.iqiyi.pps.epg.core.async.AsyncService;
import com.iqiyi.pps.epg.core.async.HeartBeatCenter;
import com.iqiyi.pps.epg.core.async.IAsyncTask;
import com.iqiyi.pps.epg.core.async.IHeartBeat;
import com.iqiyi.pps.epg.core.model.record.*;
import com.iqiyi.pps.epg.core.model.task.SimpleTask;
import com.iqiyi.pps.epg.core.model.task.SimpleTaskStatus;
import com.iqiyi.pps.epg.core.model.task.SimpleTaskType;
import com.iqiyi.pps.epg.core.service.task.SimpleTaskService;
import com.iqiyi.pps.epg.core.utils.DateTimeUtil;
import com.iqiyi.pps.epg.core.utils.RecordUtil;
import com.iqiyi.pps.epg.core.utils.RequestUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

/**
 * Created by karkarrotxu on 2018/4/20.
 */
@Service
@Transactional
public class RecordAsyncServiceImpl extends AsyncService implements InitializingBean, IHeartBeat, IRecordAsyncService {
    private static final Logger logger = LoggerFactory.getLogger(RecordAsyncServiceImpl.class);

    private final static long HEARTBEAT_DELAY = 1000 * 60; //
    private final static long HEARTBEAT_DELAY2 = 1000 * 60; //
    private final static long HEARTBEAT_DELAY3 = 1000 * 60; // 回收 计划任务 RECORD_TASK_RECYCLE ;
    private static final int SIZE_LENGTH = 1024;
    private long heartBeatTime = 0;
    private long heartBeatTime2 = 0;
    private long heartBeatTime3 = 0;
    public static String ASSIGN_WORK_IP = "10.153.195.72";//待定
    @Autowired
    private SimpleTaskService simpleTaskService;


    @Autowired
    private IRecordService recordService;


    protected boolean queryEnable() {
        return getEnable("record");
    }

    public void afterPropertiesSet() throws Exception {
        logger.info("RecordAsyncServiceImpl afterPropertiesSet");
        HeartBeatCenter.add(this);
    }

    @Override
    public void tick(long now) {
        if (now - heartBeatTime >= HEARTBEAT_DELAY) {
            heartBeatTime = now;
            logger.info("record_task_START tick");
            triggerStartOnce();
        }
        if (now - heartBeatTime2 >= HEARTBEAT_DELAY2) {
            heartBeatTime2 = now;
            logger.info("record_task_append tick");
            triggerAppendOnce();
        }

        if (now - heartBeatTime3 >= HEARTBEAT_DELAY3) {
            heartBeatTime3 = now;
            logger.info("record_col_recycle tick");
            triggerColRecycleOnce();
            logger.info("record_plan_recycle tick");
            triggerPlanRecycleOnce();
            logger.info("record_task_recycle tick");
            triggerTaskRecycleOnce();
            logger.info("record_video_recycle tick");
            triggerVideoRecycleOnce();
            logger.info("unbind_channel_signal tick");
            triggerChannelSignalRecycleOnce();
        }
    }

    public void triggerStartOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.RECORD_TASK_START.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), true);
            }
        });
    }

    public void triggerColRecycleOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.RECORD_COL_RECYCLE.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), false);
            }
        });
    }

    public void triggerPlanRecycleOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.RECORD_PLAN_RECYCLE.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), false);
            }
        });
    }

    public void triggerTaskRecycleOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.RECORD_TASK_RECYCLE.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), false);
            }
        });
    }

    public void triggerVideoRecycleOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.RECORD_VIDEO_RECYCLE.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), false);
            }
        });
    }

    public void triggerChannelSignalRecycleOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.UNBIND_CHANNEL_SIGNAL.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), false);
            }
        });
    }


    @Override
    public int changeRecordTaskRule(long planId, int execStatus) {
        int execStatusNew = 0;
        int execStatusOld = 0;

        switch (execStatus) {
            case RecordTaskRule.STATUS_USE:
                execStatusNew = 1;
                break;
            case RecordTaskRule.STATUS_STOP:
                execStatusOld = 1;
                break;
            default:
                break;
        }

        int flag = recordService.changeTaskRuleStatus(planId, execStatusNew, execStatusOld);
        if (execStatus == RecordTaskRule.STATUS_USE && flag > 0) {
            interruptRunningTask(planId);
            addRecordRuleStartTask(planId);
        }
        return 1;
    }

    @Override
    public void triggerAppendOnce() {
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList(SimpleTaskType.RECORD_TASK_APPEND.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex(), true);
            }
        });
    }

    protected void executeSimpleTaskList(int type, int status, boolean needOverride) {
        logger.info("[executeSimpleTaskList] execute type:{},status={}", type, status);
        try {
            List<SimpleTask> resultList = simpleTaskService.findList(type, status);
            if (resultList == null || resultList.size() == 0) {
                logger.info("[result empty] resultList == null :" + (resultList == null));
                return;
            }
            logger.info("[executeSimpleTaskList] execute size:" + resultList.size());
            long currentTime = System.currentTimeMillis();
            if (needOverride) {
                Collections.reverse(resultList);
            }
            List<SimpleTask> updateList = new ArrayList<SimpleTask>(SIZE_LENGTH);
            Map<Long, SimpleTask> checkMap = new HashMap<Long, SimpleTask>(SIZE_LENGTH);
            List<SimpleTask> waitToDealList = new ArrayList<SimpleTask>(SIZE_LENGTH);
            for (SimpleTask simpleTask : resultList) {
                if (currentTime > simpleTask.getExpireTime().getTime()) {
                    simpleTask.setTaskStatus(SimpleTaskStatus.EXPIRED.getStatusIndex());
                    updateList.add(simpleTask);
                } else {
                    if (needOverride) {
                        if (!checkMap.containsKey(simpleTask.getEntityId())) {
                            checkMap.put(simpleTask.getEntityId(), simpleTask);
                        } else {
                            simpleTask.setTaskStatus(SimpleTaskStatus.OVERRIDE.getStatusIndex());
                            updateList.add(simpleTask);
                        }
                    } else {
                        waitToDealList.add(simpleTask);
                    }
                }
            }
            logger.info("[executeSimpleTaskList] overtime size:" + updateList);
            if (updateList.size() > 0) {
                simpleTaskService.batchUpdateList(updateList);
            }

            if (checkMap.size() > 0) {
                waitToDealList.addAll(checkMap.values());
            }

            if (waitToDealList.size() > 0) {
                updateList.clear();

                for (SimpleTask simpleTask : waitToDealList) {
                    if (executeSimpleTask(simpleTask)) {
                        updateList.add(simpleTask);
                    }
                }
                if (updateList.size() > 0) {
                    simpleTaskService.batchUpdateList(updateList);
                }
            }
        } catch (Exception e) {
            logger.error("[executeSimpleTaskList] error", e);
        }
        logger.info("[executeSimpleTaskList] execute end");
    }

    protected boolean executeSimpleTask(SimpleTask simpleTask) {
        SimpleTaskType type = SimpleTaskType.getTypeByIndex(simpleTask.getTaskType());
        boolean flag = false;
        try {
            switch (type) {
                case RECORD_TASK_START:
                    flag = doRecordTaskStart(simpleTask);
                    break;
                case RECORD_TASK_APPEND:
                    flag = doRecordTaskAppend(simpleTask);
                    break;
                case RECORD_COL_RECYCLE:
                    flag = doRecordColRecycle(simpleTask);
                    break;
                case RECORD_PLAN_RECYCLE:
                    flag = doRecordPlanRecycle(simpleTask);
                    break;
                case RECORD_TASK_RECYCLE:
                    flag = doRecordTaskRecycle(simpleTask);
                    break;
                case RECORD_VIDEO_RECYCLE:
                    flag = doRecordVideoRecycle(simpleTask);
                    break;
                case UNBIND_CHANNEL_SIGNAL:
                    flag = doChannelSignalRecycle(simpleTask);
                    break;
            }
        } catch (Exception e) {
            logger.error("[executeSimpleTask]" + type.toString() + "[sid={" + simpleTask.getId() + "}]", e);
        }
        if (flag) {
            simpleTask.setTaskStatus(SimpleTaskStatus.COMPLETE.getStatusIndex());
            simpleTask.setCompleteTime(new Timestamp(System.currentTimeMillis()));
        }
        return flag;
    }

    private boolean doRecordTaskStart(SimpleTask simpleTask) {
        RecordPlan recordPlan = recordService.getRecordPlanById(simpleTask.getEntityId());
        if (recordPlan == null || recordPlan.getEnable() == 0) {
            logger.info("[doRecordTaskStart] recordPlan delete {}", simpleTask.getEntityId());
            doTaskError(simpleTask);
            return false;
        }
        logger.info("[doRecordTaskStart] sid={}", simpleTask.getId());
        JSONObject params = JSONObject.parseObject(simpleTask.getParams());
        long startTime = params.getLongValue("createStartTime");
        int createDay = params.getIntValue("createDay");
        long hasCreateTime = params.getLongValue("hasCreateTime");
        long stopCreateTime = DateTimeUtil.getDayEndTime(startTime) + (createDay - 1) * DateTimeUtil.DAY_TIME;
        long newStartTime = hasCreateTime != 0 ? hasCreateTime : startTime;
        RecordTaskRule recordTaskRule = recordService.getRecordTaskRuleByPlanId(recordPlan.getId());
        if (recordTaskRule.getStopTime().getTime() < stopCreateTime) {
            stopCreateTime = recordTaskRule.getStopTime().getTime();
        }
        recordService.doClearTaskBefore( recordPlan.getId(), newStartTime );
        return doCreateTask(simpleTask, newStartTime, stopCreateTime, params);
    }

    private boolean doRecordTaskAppend(SimpleTask simpleTask) {
        RecordPlan recordPlan = recordService.getRecordPlanById(simpleTask.getEntityId());
        if (recordPlan == null || recordPlan.getEnable() == 0) {
            logger.info("[doRecordTaskAppend] recordPlan delete {}", simpleTask.getEntityId());
            doTaskError(simpleTask);
            return false;
        }
        JSONObject params = JSONObject.parseObject(simpleTask.getParams());
        long checkEndTime = params.getLongValue("checkEndTime");
        long triggerTime = params.getLongValue("triggerTime");

        List<Criterion> cList = new ArrayList<Criterion>();
        cList.add(Restrictions.eq("planId", simpleTask.getEntityId()));
        cList.add(Restrictions.eq("status", 1));
        List<Order> orderList = new ArrayList<Order>();
        orderList.add(Order.desc("taskStopTime"));
        List<RecordTask> taskList = recordService.queryTaskByCriterion(cList, orderList, 1);
        if (taskList.size() == 0) {
            logger.info("[doRecordTaskAppend] taskList.size zero sid:{}", simpleTask.getId());
            return false;
        }
        long newStartTime = DateTimeUtil.parseLongFormat(taskList.get(0).getTaskStopTime());
        if (triggerTime > newStartTime) {
            logger.info("[doAutomationAppend] newStartTime lt  triggerTime . sid:{}", simpleTask.getId());
            newStartTime = triggerTime;
        }
        return doCreateTask(simpleTask, newStartTime, checkEndTime, params);
    }


    private boolean doCreateTask(SimpleTask simpleTask, long newStartTime, long stopCreateTime, JSONObject params) {
        SimpleTaskType type = SimpleTaskType.getTypeByIndex(simpleTask.getTaskType());
        if (type == SimpleTaskType.RECORD_TASK_START || type == SimpleTaskType.RECORD_TASK_APPEND) {
            return doCreateRecordTask(simpleTask, newStartTime, stopCreateTime, params);
        }
        return false;
    }

    private boolean doCreateRecordTask(SimpleTask simpleTask, long newStartTime, long stopCreateTime, JSONObject params) {
        logger.info("[doCreateRecordTask start] sid={}", simpleTask.getId());
        long taskBeginTime = System.currentTimeMillis();

        if (newStartTime < taskBeginTime) {
            newStartTime = taskBeginTime;
        }
        if (newStartTime >= stopCreateTime) {
            logger.info("[doCreateRecordTask quick end ]  sid={} newStartTime={},stopCreateTime={}",
                    simpleTask.getId(), newStartTime, stopCreateTime);
            return true;
        }
        long planId = simpleTask.getEntityId();
        RecordPlan plan = recordService.getRecordPlanById(planId);
        if (plan.getEnable() == 0) {
            logger.info("[doCreateRecordTask quick end case plan stop ]  sid={} ", simpleTask.getId());
            return true;
        }
        try {
            List<Criterion> cList = new ArrayList<Criterion>();
            cList.add(Restrictions.eq("planId", planId));
            List<RecordTaskRule> ruleList = recordService.queryTaskRuleByCriterion(cList, null);
            if (ruleList.size() != 1) {
                logger.info("[doCreateRecordTask quick end case RecordTaskRule number error ]  sid={} ,list size{}", simpleTask.getId(), ruleList.size());
                doTaskError(simpleTask);
                return false;
            }
            RecordTaskRule rule = ruleList.get(0);
            boolean overTime = newStartTime >= stopCreateTime;
            long tempCountTime = newStartTime;
            RecordTask temp = null;
            List<RecordTask> list = new ArrayList<RecordTask>(128);
            if (!overTime) {
                if (plan.getPlanType() == RecordPlan.TYPE_ALL_TIME) {
                    int batchAddNum = 150;
                    int count = 0;
                    boolean batchUpdate = false;
                    long taskDuration = 60000l * plan.getFragmentOutput();

                    int createNum = (int) ((stopCreateTime - tempCountTime) / taskDuration);
                    if (stopCreateTime - tempCountTime > taskDuration * createNum) {
                        createNum++;
                    }
                    for (int i = 0; i < createNum; i++) {
                        temp = new RecordTask();
                        temp.setPlanId(plan.getId());
                        temp.setTaskStatus(RecordTaskStatus.WAIT.getStatusIndex());
                        temp.setCreateTime(new Timestamp(taskBeginTime));
                        temp.setStatus(1);
                        temp.setTaskStartTime(DateTimeUtil.transLongFormat(tempCountTime));
                        temp.setTaskStopTime(DateTimeUtil.transLongFormat(tempCountTime + taskDuration));
                        list.add(temp);
                        tempCountTime += taskDuration;
                        count++;
                        if (i == createNum - 1) {
                            batchUpdate = true;
                        } else if (count == batchAddNum) {
                            count = 0;
                            batchUpdate = true;
                        }
                        if (batchUpdate) {
                            batchUpdate = false;
                            params.put("hasCreateTime", tempCountTime);
                            simpleTask = simpleTaskService.findById(simpleTask.getId());
                            if (simpleTask.getTaskStatus() == SimpleTaskStatus.WAIT.getStatusIndex()) {
                                simpleTask.setParams(params.toJSONString());
                            } else {
                                logger.info("simpleTask sid={} taskStatus={}", simpleTask.getId(), simpleTask.getTaskStatus());
                                return false;
                            }
                            rule.setNextExecuteTime(new Timestamp(tempCountTime));
                            recordService.editRecordTaskRule(rule);
                            recordService.saveBatchRecordTask(list);
                            list.clear();
                            simpleTaskService.saveTask(simpleTask);
                        }
                    }
                } else if (plan.getPlanType() == RecordPlan.TYPE_CYCLE_TIME) {
                    int repeatCode = plan.getRepeatCode();
                    List<Integer> dayWeekList = RecordUtil.decodeRepeatCode(repeatCode);
                    Calendar c = Calendar.getInstance();
                    c.setTimeInMillis(newStartTime);
                    int dayOfWeekValue = c.get(Calendar.DAY_OF_WEEK);
                    long tempTaskStartTime = DateTimeUtil.getZeroTime(newStartTime) + parseStartDayTime(plan.getStartDayTime());
                    long tempTaskStopTime = 0;
                    if (plan.getStopDayTime().compareTo(plan.getStartDayTime()) > 0) {
                        tempTaskStopTime = DateTimeUtil.getZeroTime(newStartTime) + parseStartDayTime(plan.getStopDayTime());
                    } else {
                        tempTaskStopTime = DateTimeUtil.getZeroTime(newStartTime) + DateTimeUtil.DAY_TIME + parseStartDayTime(plan.getStopDayTime());
                    }
                    while (tempTaskStartTime < stopCreateTime) {
                        if (dayWeekList.indexOf(dayOfWeekValue) != -1) {
                            if (newStartTime <= tempTaskStartTime) {
                                temp = new RecordTask();
                                temp.setPlanId(plan.getId());
                                temp.setTaskStatus(RecordTaskStatus.WAIT.getStatusIndex());
                                temp.setCreateTime(new Timestamp(taskBeginTime));
                                temp.setStatus(1);
                                temp.setTaskStartTime(DateTimeUtil.transLongFormat(tempTaskStartTime));
                                temp.setTaskStopTime(DateTimeUtil.transLongFormat(tempTaskStopTime));
                                list.add(temp);
                            }
                        }
                        tempTaskStartTime += DateTimeUtil.DAY_TIME;
                        tempTaskStopTime += DateTimeUtil.DAY_TIME;
                        dayOfWeekValue++;
                        if (dayOfWeekValue == 8) {
                            dayOfWeekValue = 1;
                        }
                    }
                    rule.setNextExecuteTime(new Timestamp(tempTaskStartTime));
                    recordService.editRecordTaskRule(rule);
                    recordService.saveBatchRecordTask(list);
                    list.clear();
                    simpleTaskService.saveTask(simpleTask);
                }
            }
            return true;
        } catch (Exception e) {
            logger.error("[doCreateRecordTask] sid=" + simpleTask.getId(), e);
            return false;
        } finally {
            logger.info("[sid={}][taskCostTime={}]", simpleTask.getId(), System.currentTimeMillis() - taskBeginTime);
        }
    }

    private boolean doRecordColRecycle(SimpleTask simpleTask) {
        JSONObject jsonObject = JSONObject.parseObject(simpleTask.getParams());
        long channelId = jsonObject.getLongValue("entityId");
        List<Criterion> cList = new ArrayList<Criterion>();
        cList.add(Restrictions.eq("status", 1));
        cList.add(Restrictions.eq("channelId", channelId));
        List<RecordCol> resultList = recordService.queryColByCriterion(cList, null);
        for (RecordCol temp : resultList) {
            temp.setStatus(0);
        }
        recordService.updateBatchRecordCol(resultList);
        addRecordPlanClearByChannel(channelId);
        return true;
    }

    private boolean doRecordPlanRecycle(SimpleTask simpleTask) {
        JSONObject jsonObject = JSONObject.parseObject(simpleTask.getParams());
        String mode = jsonObject.getString("mode");
        List<Criterion> cList = new ArrayList<Criterion>();
        cList.add(Restrictions.eq("status", 1));
        boolean byChannel = "channel".equals(mode);
        boolean byCol = "col".equals(mode);
        long entityId = jsonObject.getLongValue("entityId");
        if (byChannel) {
            cList.add(Restrictions.eq("channelId", entityId));
        } else if (byCol) {
            cList.add(Restrictions.eq("colId", entityId));
        }
        List<RecordPlan> plans = recordService.queryPlanByCriterion(cList, null);
        List<Long> runningIds = new ArrayList<Long>();
        List<Long> idList = new ArrayList<Long>();
        for (RecordPlan temp : plans) {
            idList.add(temp.getId());
            temp.setStatus(0);
            if (temp.getEnable() == 1) {
                temp.setEnable(0);
                runningIds.add(temp.getId());
            }
        }
        for (Long temp : runningIds) {
            recordService.changeTaskRuleStatus(temp, 0, 1);
            interruptRunningTask(temp);
        }

        if (byChannel) {
            addRecordVideoClearByChannel(entityId);
        }
        for (Long planId : idList) {
            addRecordTaskClearByPlan(planId, byChannel);
        }
        if(plans.size() > 0){
            recordService.updateBatchRecordPlan(plans);
        }
        return true;
    }

    private boolean doRecordTaskRecycle(SimpleTask simpleTask) {
        JSONObject jsonObject = JSONObject.parseObject(simpleTask.getParams());
        boolean skipVideoClear = jsonObject.getBooleanValue("skipVideo");

        List<Criterion> cList = new ArrayList<Criterion>();
        cList.add(Restrictions.eq("planId", simpleTask.getEntityId()));
        cList.add(Restrictions.eq("status", 1));
        List<RecordTask> list = null;
        List<Long> cleanList = null;
        for (int i = 0; i < 1000; i++) {
            list = recordService.queryTaskByCriterion(cList, null, 50, 0);
            if (list == null || list.size() == 0) {
                break;
            }
            cleanList = new ArrayList<Long>();
            for (RecordTask temp : list) {
                cleanList.add(temp.getId());
                temp.setStatus(0);
            }
            recordService.updateBatchRecordTask(list);
            if (!skipVideoClear) {
                addRecordVideoClearByTaskList(cleanList);
            }
        }
        return true;
    }

    private boolean doRecordVideoRecycle(SimpleTask simpleTask) {
        JSONObject jsonObject = JSONObject.parseObject(simpleTask.getParams());
        String mode = jsonObject.getString("mode");
        try {
            switch (mode) {
                case "channel":
                    recordService.deleteVideoByChannel(jsonObject.getLongValue("entityId"));
                    break;
                case "task":
                    recordService.deleteVideoByTask(jsonObject.getLongValue("entityId"));
                    break;
                case "taskList":
                    recordService.deleteVideoByTasks(jsonObject.getJSONArray("taskIds").toJSONString());
                    break;
            }
        } catch (Exception e) {
            logger.error("[doRecordVideoRecycle error] sid =" + simpleTask.getId(), e);
        }
        return true;
    }

    //wait to do
    private boolean doChannelSignalRecycle(SimpleTask simpleTask) {
        List<Criterion> list = new ArrayList<>();
        list.add(Restrictions.eq("channelId", simpleTask.getEntityId()));
        list.add(Restrictions.eq("status", 1));
        List<RecordChannelSignal> resultList = recordService.queryChannelSignalByCriterion(list, null);
        for (RecordChannelSignal temp : resultList) {
            recordService.delRecordChannelSignal(temp.getId());
        }
        return true;
    }

    private void addRecordRuleStartTask(long planId) {
        int createDay = Configuration.getInt("record.task.createDay");
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setEntityId(planId);
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());

        RecordTaskRule recordTaskRule = recordService.getRecordTaskRuleByPlanId(planId);
        long defaultStartTime = System.currentTimeMillis() + DateTimeUtil.MINUTE_TIME * 20;
        if (defaultStartTime < recordTaskRule.getStartTime().getTime()) {
            defaultStartTime = recordTaskRule.getStartTime().getTime();
        }
        jsonObject.put("createStartTime", defaultStartTime);
        jsonObject.put("createDay", createDay);
        simpleTask.setTaskType(SimpleTaskType.RECORD_TASK_START.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordRuleAppendTask(long entityId, long checkEndTime) {
        logger.info("[addRecordRuleAppendTask] entityId={},checkEndTime={}", entityId, checkEndTime);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setEntityId(entityId);
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        jsonObject.put("triggerTime", System.currentTimeMillis());
        jsonObject.put("checkEndTime", checkEndTime);
        simpleTask.setTaskType(SimpleTaskType.RECORD_TASK_APPEND.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordColClearByChannel(long channelId) {
        logger.info("[addRecordColClearByChannel] channelId={} ", channelId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mode", "channel");
        jsonObject.put("entityId", channelId);
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_COL_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordPlanClearByCol(long colId) {
        logger.info("[addRecordPlanClearByCol] col={} ", colId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mode", "col");
        jsonObject.put("entityId", colId);
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setEntityId(0);
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_PLAN_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordPlanClearByChannel(long channelId) {
        logger.info("[addRecordPlanClearByChannel] channelId={} ", channelId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mode", "channel");
        jsonObject.put("entityId", channelId);
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setEntityId(0);
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_PLAN_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordTaskClearByPlan(long planId, boolean skipVideoClear) {
        logger.info("[addRecordTaskClearByPlan] planId={} ", planId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("skipVideo", skipVideoClear);
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setEntityId(planId);
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_TASK_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordVideoClearByChannel(long channelId) {
        logger.info("[addRecordVideoClearByChannel] channelId={} ", channelId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mode", "channel");
        jsonObject.put("entityId", channelId);
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_VIDEO_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    @Override
    public void addRecordVideoClearByTask(long taskId) {
        logger.info("[addRecordVideoClearByTask] taskId={} ", taskId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mode", "task");
        jsonObject.put("entityId", taskId);
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_VIDEO_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    public void unbindChannelSignalByChannelId(long channelId) {
        logger.info("[unbindChannelSignalByChannelId] channelId={} ", channelId);
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setEntityId(channelId);
        simpleTask.setTaskType(SimpleTaskType.UNBIND_CHANNEL_SIGNAL.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
//

    }

    public void addRecordVideoClearByTaskList(List<Long> taskIds) {
        logger.info("[addRecordVideoClearByTask] taskId={} ", JSON.toJSONString(taskIds));
        SimpleTask simpleTask = new SimpleTask();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("mode", "taskList");
        jsonObject.put("taskIds", JSONArray.toJSONString(taskIds));
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(isProductionEnv() ? ASSIGN_WORK_IP : simpleTask.getServerIp());
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.RECORD_VIDEO_RECYCLE.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + 2 * DateTimeUtil.DAY_TIME));
        simpleTask.setParams(jsonObject.toJSONString());
        simpleTaskService.saveTask(simpleTask);
    }

    private void interruptRunningTask(long entityId) {
        int effectNum = simpleTaskService.interruptTask(entityId, SimpleTaskType.RECORD_TASK_START.getTypeIndex());
        logger.info("[effectNum]RECORD_TASK_START entityId {},effectNum={}:" + entityId, effectNum);
        effectNum = simpleTaskService.interruptTask(entityId, SimpleTaskType.RECORD_TASK_APPEND.getTypeIndex());
        logger.info("[effectNum]RECORD_TASK_APPEND entityId {},effectNum={}:" + entityId, effectNum);
    }

    private void doTaskError(SimpleTask simpleTask) {
        logger.info("simpleTask error id:{}", simpleTask.getId());
        simpleTask.setTaskStatus(SimpleTaskStatus.ERROR.getStatusIndex());
        simpleTaskService.saveTask(simpleTask);
    }


    private static long parseStartDayTime(String dayTime) {
        long totalTime = 0;
        totalTime += DateTimeUtil.HOUR_TIME * (getCharToInt(dayTime, 0) * 10 + getCharToInt(dayTime, 1));
        totalTime += DateTimeUtil.MINUTE_TIME * (getCharToInt(dayTime, 3) * 10 + getCharToInt(dayTime, 4));
        totalTime += DateTimeUtil.SECOND * (getCharToInt(dayTime, 6) * 10 + getCharToInt(dayTime, 7));
        return totalTime;
    }

    private static int getCharToInt(String val, int index) {
        return val.charAt(index) - 48;
    }
}
